home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 March: Reference Library / Dev.CD Mar 97 RL.toast / mac / Technical Documentation / develop / develop Issue 24 / develop Issue 24 code / Scriptable Database 1.0a15.sea / Scriptable Database 1.0a15 / Foundation / MarkToken.cp / MarkToken.cp
Encoding:
Text File  |  1996-02-20  |  13.0 KB  |  379 lines  |  [TEXT/CWIE]

  1. /*
  2.     File:        MarkToken.c
  3.  
  4.     Contains:    xxx put contents here xxx
  5.  
  6.     Written by:    Andy Nicholas, Greg Anderson, Tom Conrad, Chris Bingham, Georgiann Puckett, John Thompson-Rohrlich
  7.  
  8.     Copyright:    © 1994-1995 by Apple Computer, Inc., all rights reserved.
  9.  
  10.          <9>      6/6/95    ga        
  11.  
  12. */
  13.  
  14. #ifdef MWTRACEBACKTABLES
  15. #pragma traceback on
  16. #endif
  17.  
  18. #include "MarkToken.h"
  19. #include "ScriptableObjectList.h"
  20.  
  21. #include <AERegistry.h>
  22. #include "Exceptions.h"
  23.  
  24. //----------------------------------------------------------------------------------------
  25. // MarkTokenMergeProc: 
  26. //
  27. // This is the callback function used to merge tokens in TTokenDescriptor::AdoptToken
  28. //----------------------------------------------------------------------------------------
  29. TAbstractScriptableObject* MarkTokenMergeProc(TAbstractScriptableObject* baseToken, TAbstractScriptableObject* mergeToken)
  30.     {
  31.     return baseToken->AdoptToken(mergeToken, kAlwaysMakeCollection);
  32.     } // MarkTokenMergeProc 
  33.  
  34. //========================================================================================
  35. // CLASS TMarkToken
  36. //========================================================================================
  37.  
  38.  
  39. #pragma segment ObjectResident
  40. ImplementSmallClassData(TMarkToken, clMarkToken);
  41.  
  42. #pragma segment MarkToken
  43.  
  44. //----------------------------------------------------------------------------------------
  45. // TMarkToken::~TMarkToken: 
  46. //----------------------------------------------------------------------------------------
  47. TMarkToken::~TMarkToken()
  48.     {
  49.     if(fMarkList != nil)
  50.         {
  51.             {
  52.             for(AnIteratorOfAListOf<TAbstractScriptableObject*> iter(this->fMarkList); iter.More(); iter.Next())
  53.                 iter.Current()->DisposeDesignator();
  54.             }
  55.         
  56.         delete fMarkList;
  57.         }
  58.     } // TMarkToken::~TMarkToken 
  59.  
  60. //----------------------------------------------------------------------------------------
  61. // TMarkToken::IMarkToken: 
  62. //----------------------------------------------------------------------------------------
  63. void TMarkToken::IMarkToken()
  64.     {
  65.     if(fMarkList == nil)
  66.         fMarkList = new AListOf<TAbstractScriptableObject*>;
  67.     
  68.     TProxyToken::IProxyToken(nil);
  69.     } // TMarkToken:: IMarkToken
  70.  
  71. //----------------------------------------------------------------------------------------
  72. // TMarkToken::CloneOwnedObjects
  73. //----------------------------------------------------------------------------------------
  74. void TMarkToken::CloneOwnedObjects()
  75.     {
  76.     if(fMarkList)
  77.         {
  78.         AListOf<TAbstractScriptableObject*>* markListToClone = fMarkList;
  79.         fMarkList = new AListOf<TAbstractScriptableObject*>(markListToClone->ItemsInList());
  80.         
  81.         for(AnIteratorOfAListOf<TAbstractScriptableObject*> iter(markListToClone); iter.More(); iter.Next())
  82.             {
  83.             TAbstractScriptableObject* clonedItem = iter.Current()->CloneDesignator();
  84.             fMarkList->Add(clonedItem);
  85.             }
  86.         }
  87.     } // TMarkToken::CloneOwnedObjects
  88.     
  89. //----------------------------------------------------------------------------------------
  90. // TMarkToken::DerivedFromOSLClass: 
  91. //----------------------------------------------------------------------------------------
  92. Boolean TMarkToken::DerivedFromOSLClass(const TAETransaction& t, DescType objectClass)
  93.     {
  94.     return (objectClass == cMarkToken) || (Inherited::DerivedFromOSLClass(t, objectClass));
  95.     } // TMarkToken::DerivedFromOSLClass 
  96.  
  97. //----------------------------------------------------------------------------------------
  98. // TMarkToken::BestType
  99. //----------------------------------------------------------------------------------------
  100. DescType TMarkToken::BestType(const TAETransaction& t, DescType propertyName)
  101.     {
  102.     DescType bestType = 0;
  103.     
  104.     if((propertyName == pContents) && (fIsUnionMark == kPropertyUnion))
  105.         bestType = typeBest;
  106.     else
  107.         bestType = Inherited::BestType(t, propertyName);
  108.     
  109.     return bestType;
  110.     } // TMarkToken::BestType
  111.  
  112. //----------------------------------------------------------------------------------------
  113. // TMarkToken::DefaultType
  114. //----------------------------------------------------------------------------------------
  115. DescType TMarkToken::DefaultType(const TAETransaction& t, DescType propertyName)
  116.     {
  117.     DescType defaultType = 0;
  118.     
  119.     if((propertyName == pContents) && (fIsUnionMark == kPropertyUnion))
  120.         defaultType = typeWildCard;
  121.     else
  122.         defaultType = Inherited::DefaultType(t, propertyName);
  123.     
  124.     return defaultType;
  125.     } // TMarkToken::DefaultType
  126.     
  127. //----------------------------------------------------------------------------------------
  128. // TMarkToken::DirectObjectIterator
  129. //----------------------------------------------------------------------------------------
  130. TAbstractObjectIterator* TMarkToken::DirectObjectIterator(const TAETransaction&)
  131.     {
  132.     //
  133.     // Iterate direct objects, not elements, and do not require 'Exists' to
  134.     // be true in order to touch an object in an iteration.
  135.     //
  136.     return new TMarkTokenIterator(fMarkList, false, false);
  137.     } // TMarkToken::DirectObjectIterator
  138.  
  139. //----------------------------------------------------------------------------------------
  140. // TMarkToken::ElementIterator
  141. //----------------------------------------------------------------------------------------
  142. TAbstractObjectIterator* TMarkToken::ElementIterator(const TAETransaction&)
  143.     {
  144.     //
  145.     // If this is a 'union' mark, then iterate the elements of the
  146.     // items in the mark list.  Otherwise, iterate the direct objects
  147.     // of the items in the mark list.
  148.     //
  149.     return new TMarkTokenIterator(fMarkList, IsUnionMark(), true);
  150.     } // TMarkToken::ElementIterator
  151.  
  152. //----------------------------------------------------------------------------------------
  153. // TMarkToken::AdoptToken: 
  154. //
  155. // See TAbstractScriptableObject::AddThisToMarkToken for an explanation of how this
  156. // routine is commonly used.
  157. //----------------------------------------------------------------------------------------
  158. TAbstractScriptableObject* TMarkToken::AdoptToken(TAbstractScriptableObject* token, TypeOfMarkToken /*isUnionMark*/)
  159.     {
  160.     //
  161.     // ◊Script:  Should we test to see if this->IsUnionMark() == isUnionMark?
  162.     // What would we do if that wasn't the case?  Call this->SetUnionMark(isUnionMark);?
  163.     //
  164.     if(token != nil)
  165.         fMarkList->Add(token);
  166.     
  167.     return this;
  168.     } // TMarkToken::AdoptToken 
  169.  
  170. //----------------------------------------------------------------------------------------
  171. // TMarkToken::AddThisToMarkToken: 
  172. //
  173. // See TAbstractScriptableObject::AddThisToMarkToken for a complete description of how
  174. // this code works.  This routine works the same way, but it removes the contents of
  175. // this mark token and adds it, one item at a time, to the mark token provided.  This
  176. // prevents having mark tokens inside of mark tokens.
  177. //----------------------------------------------------------------------------------------
  178. void TMarkToken::AddThisToMarkToken(TAbstractScriptableObject*& markToken, TypeOfMarkToken isUnionMark)
  179.     {
  180.     if(markToken == nil)
  181.         {
  182.         markToken = this;
  183.         }
  184.     else
  185.         {
  186.         for(AnIteratorOfAListOf<TAbstractScriptableObject*> iter(this->fMarkList); iter.More(); iter.Next())
  187.             {
  188.             markToken = markToken->AdoptToken(iter.Current(), isUnionMark);
  189.             }
  190.         
  191.         //
  192.         // Self deletion is generally evil, but the semantics of this
  193.         // call is to pass ownership of this token to the provided
  194.         // mark token, so no code should ever reference this object after
  195.         // calling AddThisToMarkToken.
  196.         //
  197.         delete this;
  198.         }
  199.     } // TMarkToken::AddThisToMarkToken 
  200.  
  201. //----------------------------------------------------------------------------------------
  202. // TMarkToken::AdjustMarks: 
  203. //----------------------------------------------------------------------------------------
  204. void TMarkToken::AdjustMarks(long newStart, long newStop)
  205.     {
  206.     unsigned long i = 1;
  207.     unsigned long total = this->fMarkList->ItemsInList();
  208.     Boolean reverseOrderOfList = false;
  209.     
  210.     //
  211.     // First, adjust for negative indices
  212.     //
  213.     if(newStart < 0)
  214.         newStart = total + 1 + newStart;
  215.     if(newStop < 0)
  216.         newStop = total + 1 + newStop;
  217.     
  218.     //
  219.     // Next, swap newStart and newStop if their order is reversed
  220.     //
  221.     if(newStart > newStop)
  222.         {
  223.         long temp = newStop;
  224.         newStop = newStart;
  225.         newStart = temp;
  226.         reverseOrderOfList = true;
  227.         }
  228.     
  229.     //
  230.     // Once we have the correct range, prune out the items
  231.     // that aren't wanted.
  232.     //
  233.     for(AnIteratorOfAListOf<TAbstractScriptableObject*> iter(this->fMarkList); iter.More(); iter.Next())
  234.         {
  235.         if((i < newStart) || (i > newStop))
  236.             {
  237.             iter.Current()->DisposeDesignator();
  238.             iter.RemoveCurrent();
  239.             }
  240.         ++i;
  241.         }
  242.     
  243.     //
  244.     // Finally, reverse the order of the list if
  245.     // the start was greater than the stop
  246.     //
  247.     if(reverseOrderOfList)
  248.         {
  249.         this->fMarkList->ReverseOrderOfList();
  250.         }
  251.     } // TMarkToken::AdjustMarks 
  252. //========================================================================================
  253. // Class TMarkTokenIterator
  254. //========================================================================================
  255.  
  256. //----------------------------------------------------------------------------------------
  257. // TMarkTokenIterator::~TMarkTokenIterator
  258. //----------------------------------------------------------------------------------------
  259. TMarkTokenIterator::~TMarkTokenIterator()
  260.     {
  261.     delete fListIter;
  262.     delete fCurrentIter;
  263.     if(fDeleteListOnDestruction)
  264.         delete fMarkList;
  265.     }
  266.  
  267. //----------------------------------------------------------------------------------------
  268. // TMarkTokenIterator::SetupCurrentIterator
  269. //----------------------------------------------------------------------------------------
  270. void TMarkTokenIterator::SetupCurrentIterator(const TAETransaction& t)
  271.     {
  272.     delete fCurrentIter;
  273.     fCurrentIter = nil;
  274.  
  275.     while((fCurrentIter == nil) && (fListIter->More(t)))
  276.         {
  277.         TAbstractScriptableObject* listIterCurrent = fListIter->Current(t);
  278.         REQUIREVALIDPOINTER(listIterCurrent); // If nil, fListIter->More should have been false
  279.         
  280.         //
  281.         // If 'fRequireExists' is true, then skip any item whose
  282.         // 'Exists' method returns false.
  283.         //
  284.         // Q: Why ever check to see if the item exists?  If the item doesn't
  285.         // exist, won't its iterator's More() method always return false?
  286.         //
  287.         // A: This is a very important concept.  It is true that whenever
  288.         // an empty iterator is returned, Exists will always return false.
  289.         // However, in some cases, Exists will return false even if the
  290.         // iterator has elements.  One example of this is a token to a window
  291.         // that is not open; Exists returns false, because the window does not
  292.         // exist (and should not be counted); however, the direct object iterator
  293.         // will return it so that the token will continue to get messages
  294.         // (e.g. "open").
  295.         //
  296.         if((fRequireExists == false) || (listIterCurrent->Exists(t) == true))
  297.             {
  298.             TAbstractObjectIterator* testIterator = nil;
  299.             
  300.             //
  301.             // If we're not iterating elements, then we're iterating direct objects
  302.             //
  303.             if(fIterateElements)
  304.                 testIterator = listIterCurrent->ElementIterator(t);
  305.             else
  306.                 testIterator = listIterCurrent->DirectObjectIterator(t);
  307.             
  308.             // listIterCurrent->DisposeDesignator();
  309.             
  310.             //
  311.             // Skip any iterator with no elements (should be rare...)
  312.             //
  313.             if((testIterator == nil) || (testIterator->More(t) == false))
  314.                 {
  315.                 if(testIterator != nil)
  316.                     testIterator->Release();
  317.                 fListIter->Next(t);
  318.                 }
  319.             else
  320.                 fCurrentIter = testIterator;
  321.             }
  322.         }
  323.     }
  324.     
  325. //----------------------------------------------------------------------------------------
  326. // TMarkTokenIterator::Reset
  327. //----------------------------------------------------------------------------------------
  328. void TMarkTokenIterator::Reset(const TAETransaction& t, Boolean iterationDirection /*= kForwardIteration*/)
  329.     {
  330.     if(fListIter == nil)
  331.         fListIter = new TScriptableObjectListIterator(fMarkList);
  332.     
  333.     fDirection = iterationDirection;
  334.     fListIter->Reset(t, iterationDirection);
  335.     
  336.     this->SetupCurrentIterator(t);
  337.     }
  338.     
  339. //----------------------------------------------------------------------------------------
  340. // TMarkTokenIterator::More
  341. //----------------------------------------------------------------------------------------
  342. Boolean TMarkTokenIterator::More(const TAETransaction& t) const
  343.     {
  344.     return fCurrentIter ? fCurrentIter->More(t) : false;
  345.     }
  346.     
  347. //----------------------------------------------------------------------------------------
  348. // TMarkTokenIterator::Next
  349. //----------------------------------------------------------------------------------------
  350. void TMarkTokenIterator::Next(const TAETransaction& t)
  351.     {
  352.     if(fCurrentIter)
  353.         {
  354.         fCurrentIter->Next(t);
  355.         if(fCurrentIter->More(t) == false)
  356.             {
  357.             fListIter->Next(t);
  358.             this->SetupCurrentIterator(t);
  359.             }
  360.         }
  361.     }
  362.     
  363. //----------------------------------------------------------------------------------------
  364. // TMarkTokenIterator::Current
  365. //----------------------------------------------------------------------------------------
  366. TAbstractScriptableObject* TMarkTokenIterator::Current(const TAETransaction& t)
  367.     {
  368.     return fCurrentIter ? fCurrentIter->Current(t) : nil;
  369.     }
  370.  
  371. //----------------------------------------------------------------------------------------
  372. // TMarkTokenIterator::SearchDeep
  373. //----------------------------------------------------------------------------------------
  374. void TMarkTokenIterator::SearchDeep(const TAETransaction& t, TAbstractCollector* collector, DescType desiredClass, TAbstractSearchSpec* searchSpec)
  375.     {
  376.     this->RecursiveSearchDeep(t, collector, desiredClass, searchSpec);
  377.     } // TMarkTokenIterator::SearchDeep
  378.  
  379.